# Well Documented Tetriz ~ Version 0.2 ~ Phear The Ceal ~ <Name of someone who helped goes here>
# This is going to be a general Tetris clone. Feel free to contribute any code or suggestions.
# My goal is to have it done in 2 weeks and also make it very well documented with a log file and such.
# 
# June 21: Released version 0.1 by creating the __init__ for the Block() class. __init__ includes every block type that
# we will be seeing in the game. If you don't understand how it works just contact me and I'll tell you all about it.
#
# June 26: Added collision detection and continuouse falling blocks

# Import libraries for using pygame, and random for falling blocks
import pygame, random
pygame.init()
# This import makes certain variable names I'll be using a lot more accessible
from pygame.locals import *

# These will be globals that I'll use to refer to the size  of the screen. Will change later for control panel on side
WINDOWHEIGHT = 15 * 19
WINDOWWIDTH = 15 * 10

# This makes the screen I'll be drawing to in the future.
Surface = pygame.display.set_mode((WINDOWWIDTH, WINDOWHEIGHT))
# Words at the top bar of the window are made here. This line must be after the above line.
pygame.display.set_caption('Well Documented Tetriz')
# This will control the FPS in the main loop
FPS = mainClock = pygame.time.Clock()

class Block():
	#This will be the object for any block that falls. That way they are all under the same rules.
	
	def __init__(self):
		# Set up a block as it appears. I want the bottom Y value to be 0 (at the top) and arrangment to be random.
		
		self.block_size = 15 # Nice round number for a block size. Also the offset of movements the blocks will make.
		
		self.renew()
		
	def renew(self):
		# Since dictionaries aren't immutable, this function resets the starting positions of every block.
		
		# First, I'll make a list of dictionaries that hold info for the different types of arrangements that can be used.
		# My idea was to have names for each four blocks and make their positions all relative to an adjacent block starting from
		# the first one. first_block's inital y value is 0 making the shape appear one block down onto the screen. The first_block
		# will always be on the bottome and therefore the first block to appear on screen.
		self.square_block = {'color':(0, 255, 255), # Cyan
		'first_block':pygame.Rect(WINDOWWIDTH / 2, 0, self.block_size,self.block_size), #bottom-right
		'second_block':pygame.Rect((WINDOWWIDTH / 2) - self.block_size, 0, self.block_size,self.block_size), #bottom-left
		'third_block':pygame.Rect(WINDOWWIDTH / 2, 0-self.block_size, self.block_size, self.block_size), #top-right
		'fourth_block':pygame.Rect((WINDOWWIDTH /2)-self.block_size, 0-self.block_size, self.block_size, self.block_size) } #top-left
		
		# Notice I use a dictionary to sum up all the things about the block. I like this system and will be using it whenever
		# I can unless I find a better one. Lots of copy pasting as you can see to make each type of block
		self.line_block = {'color':(255,0,255), # Pink!
		'first_block':pygame.Rect(WINDOWWIDTH / 2, 0, self.block_size, self.block_size,), #bottom
		'second_block':pygame.Rect(WINDOWWIDTH / 2, (0 - self.block_size), self.block_size,self.block_size), #up one
		'third_block':pygame.Rect(WINDOWWIDTH / 2, (0 - (self.block_size * 2)), self.block_size, self.block_size), #up two
		'fourth_block':pygame.Rect(WINDOWWIDTH /2, (0 - (self.block_size * 3)), self.block_size, self.block_size ) } #top
		# Okay, line_block was pretty easy. All I had to do was make the y value of the last three blocks all one block_size higher
		
		self.L_block = {'color':(255,0,0), # Red
		'first_block':pygame.Rect(WINDOWWIDTH / 2, 0, self.block_size,self.block_size), #bottom-right
		'second_block':pygame.Rect((WINDOWWIDTH / 2) - self.block_size, 0, self.block_size,self.block_size), #bottom-left
		'third_block':pygame.Rect((WINDOWWIDTH / 2) - self.block_size, (0 - self.block_size), self.block_size, self.block_size), #middle
		'fourth_block':pygame.Rect((WINDOWWIDTH / 2) - self.block_size, (0 - (self.block_size * 2)), self.block_size, self.block_size ) } #top
		# You get the idea.		
		
		self.reverse_L_block = {'color':(0,0,255), # Blue
		'first_block':pygame.Rect(WINDOWWIDTH / 2, 0, self.block_size,self.block_size), #bottom-right
		'second_block':pygame.Rect((WINDOWWIDTH / 2) - self.block_size, 0, self.block_size,self.block_size), #bottom-left
		'third_block':pygame.Rect(WINDOWWIDTH / 2, (0 - self.block_size), self.block_size, self.block_size), #middle
		'fourth_block':pygame.Rect(WINDOWWIDTH / 2, (0 - (self.block_size * 2)), self.block_size, self.block_size ) } #top
		
		self.T_block = {'color':(255,255,0), # Yellow
		'first_block':pygame.Rect(WINDOWWIDTH / 2, 0, self.block_size,self.block_size), #bottom
		'second_block':pygame.Rect(WINDOWWIDTH / 2, (0 - self.block_size), self.block_size,self.block_size), #top-middle
		'third_block':pygame.Rect((WINDOWWIDTH / 2) - self.block_size, (0 - self.block_size), self.block_size, self.block_size), #top-left
		'fourth_block':pygame.Rect((WINDOWWIDTH / 2) + self.block_size, (0 - self.block_size), self.block_size, self.block_size ) } #top-right
		
		self.squigly_block = {'color':(0,255,0), # Green
		'first_block':pygame.Rect(WINDOWWIDTH / 2, 0, self.block_size,self.block_size), #bottom
		'second_block':pygame.Rect(WINDOWWIDTH / 2, (0 - self.block_size), self.block_size,self.block_size), #middle-right
		'third_block':pygame.Rect((WINDOWWIDTH / 2) - self.block_size, (0 - self.block_size), self.block_size, self.block_size), #middle-left
		'fourth_block':pygame.Rect((WINDOWWIDTH / 2) - self.block_size, (0 - (self.block_size * 2)), self.block_size, self.block_size ) } #top
		
		self.reverse_squigly_block = {'color':(255,128,0), # Orange!
		'first_block':pygame.Rect(WINDOWWIDTH / 2, 0, self.block_size,self.block_size), #bottom
		'second_block':pygame.Rect(WINDOWWIDTH / 2, (0 - self.block_size), self.block_size,self.block_size), #middle-left
		'third_block':pygame.Rect((WINDOWWIDTH / 2) + self.block_size, (0 - self.block_size), self.block_size, self.block_size), #middle-right
		'fourth_block':pygame.Rect((WINDOWWIDTH / 2) + self.block_size, (0 - (self.block_size * 2)), self.block_size, self.block_size ) } #top
		
		# Phew! Now that's all done I will make a list of it all called block_types
		self.block_types = [self.square_block, self.line_block, self.L_block, self.reverse_L_block, self.T_block, self.squigly_block, self.reverse_squigly_block]
		# This will set the next block to appear.
		self.next_block = random.choice(self.block_types)
		
	def adjust_check(self, current_block, mv):
		self.next_position = {}
		for event in pygame.event.get():
			if event.type == KEYDOWN:
				if event.key == K_LEFT:
					mv == (-1 * self.block_size)
				elif event.key == K_RIGHT:
					mv = self.block_size
				else: 
					return current_block # This the original position, so kinda nothing
					
				for block in current_block:
					if block == 'color': self.next_position[block] = current_block[block]; continue
					self.next_position[block] = current_block[block].move(mv, 0)
				return self.next_position
		return current_block

		
Block = Block()
nextb = Block.next_block
# Levels are actually a reflection of speed
level = 5
# Old blocks are blocks that you've already landed
old_blocks = []
mv = 0

while True:
	for event in pygame.event.get():
		# QUIT means user has presses the x button on the window
		if event.type == QUIT:
			pygame.quit()
			exit()
		if event.type == KEYDOWN:
			if event == K_LEFT:
				mv = (-1 * self.block_size)
			elif event == K_RIGHT:
				mv = self.block_size
			print(" NUMBER 1 WORKS")

	# This redraws the black background onto the screen
	Surface.fill((0,0,0))
	
	# This controls the blocks left and right movement.
	next_pos = Block.adjust_check(nextb, mv)
	print(next_pos == nextb)
	for zergling in next_pos:
		if zergling == 'color': continue # Lester doesn't like colored zlings
		for shape in old_blocks:
			for b in shape:
				if b == 'color': continue # Skip color for collision detection
				if shape[b].colliderect(next_pos[zergling]):
					pass
					print("OH CRAAAAAP!")
				else:
					nextb = next_pos
					break
	
	# This moves the nextb block and draws them
	for b in nextb:
		if b == 'color': continue
		if nextb[b].move(0, 15).bottom < WINDOWHEIGHT: # If it is above the bottom
			nextb[b].move_ip(0, Block.block_size) # Move it down 
			pygame.draw.rect(Surface, nextb['color'], nextb[b]) # Then draw it
			
	# This draws the old blocks and checks the current ones
	for b in nextb:
		if b == 'color': continue # Because we want to skip this one
		for block in old_blocks:
			Block.renew() 
			for c in block:
				if c == 'color': continue #skip color
				pygame.draw.rect(Surface, block['color'], block[c])
				if nextb[b].colliderect(block[c].move(0, -1 * Block.block_size)):
					# if the falling block hits into an old block it stops and makes a new nextb
					old_blocks.append(nextb) # nextb becomes an old block that just sits there
					Block.renew() # Reset block positions
					nextb = Block.next_block # And get a new block, fresh and ready
		
		if nextb[b].move(0, 15).bottom < WINDOWHEIGHT:
			# This is for when the current block falls onto the ground
			pass
		else:
			# If it does hit the ground, do the same thing that happened when it hits an old block
			old_blocks.append(nextb)
			Block.renew()
			nextb = Block.next_block

	# I'll have the FPS control the fall speed. May change this later some how.
	FPS.tick(level * 2)
	pygame.display.update()